home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Magazin/MacEasy 19
/
Mac Magazin and MacEasy Magazine CD - Issue 19.iso
/
Utilities
/
CornerClock ƒ
/
CornerClock.p
< prev
next >
Wrap
Text File
|
1996-02-04
|
9KB
|
388 lines
{
CornerClock is a pascal program based upon Masafumi Ueda's MBarClock program.
MBarClock was a program which displayed the time or date in the menu bar to the left
of the Apple menu. CornerClock uses that same feature and adds sound.
I converted Masafumi's MBarClock from C to Pascal, and then began forging it into
a chime replacement program. Currently, if you have long chimes activated with your
clock which comes with system 7.5, you may experience a very annoying distorted
sound which interrupts your chime. This is a known bug with the system, as it does not
appear to lock the sound handle when it plays it (it should lock it because it plays it
asynchronously). CornerClock plays the hourly chime asynchronously, but locks the
handle so you get a smooth play.
CornerClock will play a grandfather clock chime on the hour (3 chimes as 3:00, 4 at 4:00, etc.).
When you place the cursor over the time, it will change to the date for 2 seconds, then change back
to the time (same feature in MBarClock except now there is sound). I've also added some menus
to CornerClock so that you can toggle the date and time, and force a chime.
There are many enhancements which can be made, like changing the chime sound, changing the
volume, etc., but I'm releasing it as is to provide the Pascal community with some more sample
Pascal code. Feel free to send me any questions or notes of thanks.
CornerClock ©Bill Catambay, 1996, catambay@aol.com
All rights reserved worldwide.
}
Program CornerClock;
Uses
Toolbox, Sound, Resources, Icons;
Var
AppleMenu, FileMenu, EditMenu: MenuHandle;
ClockPort: CGrafPtr;
NUMs: array[0..10] of CIconHandle;
running: Boolean;
ClockRect: array[0..3] of Rect;
Corner: Rect;
bkGnd: RgnHandle;
dispStat: integer;
chimes: integer;
chimeStart: longint;
dateStart: longint;
gBackground: boolean;
sounds: array[0..3] of SndListHandle;
sndChans: array[0..3] of SndChannelPtr;
backupChan: SndChannelPtr;
forceChime: boolean;
Const
kDisplayTime = 0;
kDisplayDate = 1;
kChime = 2;
kAbout = 3;
Procedure Die;
begin
SysBeep(1);
SysBeep(1);
SysBeep(1);
ExitToShell;
end;
Procedure CheckMachine;
Var
sysEnv: SysEnvRec;
i: integer;
begin
i := SysEnvirons(curSysEnvVers, sysEnv);
if i <> noErr then
Die;
if not sysEnv.hasColorQD then
Die;
if sysEnv.systemVersion < $700 then
Die;
end;
Procedure OpenClockPort;
begin
ClockPort := CGrafPtr(NewPtrClear(sizeof(CGrafPort)));
if ClockPort = NIL then
Die;
OpenCPort(ClockPort);
end;
Procedure SetupMenu;
begin
ClearMenuBar;
AppleMenu := GetMenu(128);
InsertMenu(AppleMenu,0);
AppendResMenu(AppleMenu,'DRVR');
FileMenu := GetMenu(129);
InsertMenu(FileMenu,0);
EditMenu := GetMenu(130);
InsertMenu(EditMenu,0);
DrawMenuBar;
end;
Procedure LoadIcons;
Var
i: integer;
begin
for i := 0 to 10 do
NUMs[i] := GetCIcon(2000 + i);
end;
Procedure SetupRects;
Var
rgn: RgnHandle;
r: Rect;
begin
SetRect(ClockRect[0], 2,2,10,10);
SetRect(ClockRect[1], 8,2,16,10);
SetRect(ClockRect[2], 2,10,10,18);
SetRect(ClockRect[3], 8,10,16,18);
bkGnd := NewRgn;
SetRect(corner,0,0,16,19);
RectRgn(bkGnd,corner);
UnionRect(ClockRect[0], ClockRect[3], r);
r.bottom := r.bottom - 1;
r.right := r.right - 2;
rgn := NewRgn;
RectRgn(rgn, r);
DiffRgn(bkGnd, rgn, bkGnd);
DisposeRgn(rgn);
end;
Procedure InitAppl;
Var
i: integer;
begin
CheckMachine;
OpenClockPort;
SetupMenu;
LoadIcons;
SetupRects;
dispStat := kDisplayTime;
running := true;
chimes := 0;
chimeStart := 0;
forceChime := False;
gBackground := false;
for i := kDisplayTime to kAbout do
begin
sounds[i] := SndListHandle(GetResource(soundListRsrc,128 + i));
HLockHi(Handle(sounds[i]));
sndChans[i] := NIL;
end;
backupChan := NIL;
end;
Procedure DoSound(sndID: integer);
Var
err: OSErr;
sndCmd: SndCommand;
sndHead: SoundHeaderPtr;
SndChanStat: SCStatus;
begin
if sounds[sndID] = NIL then
begin
sysBeep(1);
exit(DoSound);
end;
if (sndChans[sndID] <> NIL) and (backupChan <> NIL) then
begin
err := SndDisposeChannel(backupChan, True);
backupChan := NIL;
end;
if sndChans[sndID] <> NIL then
begin
backupChan := sndChans[sndID];
sndChans[sndID] := NIL;
end;
err := SndNewChannel(sndChans[sndID], sampledSynth, 0, NIL);
if (err <> noErr) or (sndChans[sndID] = NIL) then
begin
sysBeep(1);
exit(DoSound);
end;
sndHead := SoundHeaderPtr(longint(sounds[sndID]^) + 20);
sndCmd.cmd := bufferCmd;
sndCmd.param1 := 0;
sndCmd.param2 := ORD4(sndHead);
err := SndDoCommand(sndChans[sndID], sndCmd, false);
err := SndChannelStatus(sndChans[sndID], sizeof(SndChanStat), @SndChanStat);
if err <> noErr then
begin
sysBeep(1);
err := SndDisposeChannel(sndChans[sndID], True);
sndChans[sndID] := NIL;
exit(DoSound);
end;
{
chimeStart := TickCount;
While SndChanStat.scChannelBusy and (not Button) and (Err = NoErr) and (SndArray[1] <> NIL) do
Err := SndChannelStatus(SndArray[1], sizeof(SndChanStat), @SndChanStat);}
end;
Procedure DoAbout;
Var
p: GrafPtr;
d: DialogPtr;
begin
GetPort(p);
d := GetNewDialog(128, NIL, WindowPtr(-1));
DrawDialog(d);
DoSound(kAbout);
repeat until Button;
DisposeDialog(d);
SetPort(p);
FlushEvents(mDownMask, 0);
end;
Procedure SwitchView;
begin
dispStat := (dispStat + 1) mod 2;
doSound(dispStat);
if dispStat = kDisplayDate then
dateStart := TickCount;
end;
Procedure DoMenu(SelMenu: longint);
Var
item,i: integer;
s: Str255;
begin
item := LoWord(SelMenu);
case HiWord(SelMenu) of
128: if item = 1 then
DoAbout
else
begin
GetMenuItemText(AppleMenu, item, s);
i := OpenDeskAcc(s);
end;
129: case item of
1,2: SwitchView;
3: forceChime := True;
5: running := false;
{CASE} end;
{CASE} end;
HiliteMenu(0);
end;
Procedure UpdateWindow(wp: WindowPtr);
begin
SetPort(wp);
BeginUpdate(wp);
EndUpdate(wp);
end;
Procedure DrawDigit(upper,lower: integer; upShow10, loShow10: boolean);
Var
p: GrafPtr;
begin
GetPort(p);
SetPort(GrafPtr(ClockPort));
ForeColor(blackColor);
PaintRgn(bkGnd);
if (upper >= 10) | upShow10 then
PlotCIcon(ClockRect[0], NUMs[ (upper div 10) mod 10])
else
PlotCIcon(ClockRect[0], NUMs[10]);
PlotCIcon(ClockRect[1], NUMs[upper mod 10]);
if (lower >= 10) | loShow10 then
PlotCIcon(ClockRect[2], NUMs[(lower div 10) mod 10])
else
PlotCIcon(ClockRect[2], NUMs[10]);
PlotCIcon(ClockRect[3], NUMs[lower mod 10]);
SetPort(p);
end;
Procedure DrawClock;
Const
chimeOn = 0;
Var
dt: DateTimeRec;
p: GrafPtr;
pt: point;
begin
GetPort(p);
SetPort(GrafPtr(ClockPort));
GetTime(dt);
GetMouse(pt);
if PtInRect(pt, corner) and (dispStat = kDisplayTime) then
SwitchView;
if (dispStat = kDisplayDate) & (dateStart + 300 < TickCount) then
SwitchView;
ForeColor(blackColor);
PaintRgn(bkGnd);
case dispStat of
kDisplayDate: DrawDigit(dt.month, dt.day, false, false);
kDisplayTime: DrawDigit(dt.hour mod 12, dt.minute, false, true);
{CASE} end;
if ((dt.minute = chimeOn) or forceChime) and (chimes = 0) then
chimes := dt.hour mod 12;
if (chimes > 0) & ((chimeStart = 0) | (chimeStart + 120 < TickCount)) then
begin
doSound(kChime);
chimeStart := TickCount;
dec(chimes);
if chimes = 0 then
dec(chimes);
end
else if (chimes = -1) & (dt.minute <> chimeOn) then
begin
chimes := 0;
forceChime := False;
chimeStart := 0;
end;
SetPort(p);
end;
Procedure MainLoop;
Var
event: EventRecord;
dw: WindowPtr;
ascii: char;
sleep: longint;
i: integer;
err: OSErr;
begin
repeat
DrawClock;
if chimes > 0 then
sleep := 1
else
sleep := 20;
if WaitNextEvent(everyEvent, event, sleep, NIL) then
case event.what of
mouseDown: case FindWindow(event.where, dw) of
inMenuBar: DoMenu(MenuSelect(event.where));
{CASE} end;
keyDown: begin
ascii := chr(BAnd(event.message,charCodeMask));
if BAnd(event.modifiers,cmdKey) > 0 then
DoMenu(MenuKey(ascii));
end;
updateEvt: UpdateWindow(WindowPtr(event.message));
osEvt: if BAnd(brotl(event.message,8),$FF) = suspendResumeMessage then
gBackground := BAnd(event.message,resumeFlag) = 0;
{CASE} end;
until not running;
DisposeRgn(bkGnd);
for i := 0 to 2 do
begin
HUnLock(Handle(sounds[i]));
DisposeHandle(Handle(sounds[i]));
err := SndDisposeChannel(sndChans[i], True);
end;
if backupChan <> NIL then
err := SndDisposeChannel(backupChan, True);
end;
begin
InitToolbox;
FlushEvents(everyEvent, 0);
InitAPPL;
MainLoop;
end.